﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml.Serialization;
using Castle.Core.Interceptor;

namespace WcfPOXCommunication
{
    public class RequestProcessor: IRequestProcessor
    {
        //TODO: Finish Implementation
        //TODO: code unit tests
        public ServiceRequest Encode(IInvocation invocation)
        {
            var arguments = invocation.Arguments;
            var parameterList = new List<string>();
            var parameters = string.Empty;

            if (arguments.Length > 0)
            {
                foreach (var argument in arguments)
                {
                    var serializer = new XmlSerializer(argument.GetType(), argument.GetType().Name);
                    var sb = new StringBuilder();
                    using (var ms = new StringWriter(sb))
                    {
                        serializer.Serialize(ms, argument);
                        parameterList.Add(sb.ToString());
                    }
                }
                var parameterSerializer = new XmlSerializer(parameterList.GetType());
                var paramSb = new StringBuilder();
                using (var ms = new StringWriter(paramSb))
                {
                    parameterSerializer.Serialize(ms, parameterList);
                }
                parameters = paramSb.ToString();
            }

            return new ServiceRequest
                       {
                           ServiceName = invocation.Method.DeclaringType.AssemblyQualifiedName,
                           MethodName = invocation.Method.Name,
                           Parameters = parameters
                       };
        }

        //TODO: Finish Implementation
        //TODO: code unit tests
        public InvokerSpecification Decode(ServiceRequest request)
        {
            // process parameters as defined in method to be invoked
            var serviceType = Type.GetType(request.ServiceName);
            var mi = serviceType.GetMethod(request.MethodName);
            var pis = mi.GetParameters();
            var parameters = new object[pis.Length];

            if (!string.IsNullOrEmpty(request.Parameters))
            {
                List<string> parameterList = null;
                var parameterSerializer = new XmlSerializer(typeof(List<string>));
                using (var sr = new StringReader(request.Parameters))
                {
                    parameterList = (List<string>)parameterSerializer.Deserialize(sr);
                }
                for (var idx = 0; idx < parameterList.Count; idx++)
                {
                    var paramStr = parameterList[idx];
                    var type = pis[idx].ParameterType;
                    var serializer = new XmlSerializer(type, type.Name);
                    using (var sr = new StringReader(paramStr))
                    {
                        parameters[idx] = serializer.Deserialize(sr);
                    }
                }
            }

            return new InvokerSpecification
                       {
                           ServiceType = serviceType,
                           Method = mi,
                           Parameters = parameters
                       };
        }
    }
}